/** boot/bootsect.S

	1. 把引导扇区从 0x07c0 移动到 0x9000 继续执行
	2. 加载 setup 到 0x9020 
	3. 加载 system 到 0x1000 
	4. 跳转到 0x9020 执行 setup
*/

.code16

#include <linux/config.h>

.equ BootSeg,	DEF_BOOTSEG
.equ InitSeg,	DEF_INITSEG
.equ SysSeg,	DEF_SYSSEG
.equ SetupSeg,	DEF_SETUPSEG
.equ SysSize,	DEF_SYSSIZE
.equ EndSeg,	SysSeg+SysSize
.equ SetupLen,	4
.equ RootDev,	0x0302
.equ SwapDev,	0

	# load boot sector to InitSeg and continue...
	ljmp $BootSeg, $start
start:
	mov $BootSeg, %ax
	mov %ax, %ds 
	mov $InitSeg, %ax 
	mov %ax, %es 
	mov $256, %cx 
	sub %si, %si 
	sub %di, %di 
    cld     # DF=0, si,di递增
	rep 
	movsw
	ljmp $InitSeg, $go 
go:
	mov $0xfef4, %di 
	mov %ax, %ds 
	mov %ax, %ss 
	mov %di, %sp 		# 0xff00-12(参数表）
	
	# 复制参数表 0:0x78 => 0x9000:0xfef4 
	mov %cx, %fs
	mov $0x78, %bx 

	push %ds 
	lds %fs:(%bx), %si 
	mov $6, %cx 
	push %di 
	cld 
	rep 
	movsw 
	pop %di 
	pop %ds 

	movb $18, 4(%di)	# 修改参数表偏移4：最大扇区数
	mov %di, %fs:(%bx)	# 中断向量 0x1E 指向新表
	mov %es, %fs:2(%bx)

	xor %ah, %ah
	xor %dl, %dl 
	int $0x13		# 复位软盘控制器
load_setup:
	xor %dx, %dx 
	mov $0x0002, %cx 
	mov $0x0200, %bx 
	mov $0x0200+SetupLen, %ax 
	int $0x13
	jnc ok_load_setup
	mov $0x0000, %dx 
	mov $0x0000, %ax 
	int $0x13
	jmp load_setup
ok_load_setup:

	# get sectors
	mov $0x00, %dl 		# dl=0 软盘
	mov $0x0800, %ax 	# ah=8, 获取驱动器参数
	int $0x13
	mov $0x00, %ch 		# cl 0-5位：扇区数
	mov %cx, %cs:sectors 	

	# load system
	mov $SysSeg, %ax 
	mov %ax, %es 
	call read_it	# 读 system 到 es:bx
	call kill_motor
	
	ljmp $SetupSeg, $0

sectors: .word 0
sread:	 .word 1+SetupLen
head:	 .word 0
track: 	 .word 0

read_it:
	mov %es, %ax 
	test $0x0fff, %ax	# 段对齐，ZF置位
die:
	jne die 
	xor %bx, %bx 
rp_read:
	mov %es, %ax 
	cmp $EndSeg, %ax 
	jb ok1_read		# jb: 小于跳转
	ret 
ok1_read:
	mov %cs:sectors, %ax 
	sub sread, %ax 	 # al: 每磁道所读扇区数
	mov %ax, %cx 
	shl $9, %cx 
	add %bx, %cx 
	jnc ok2_read 	# 每次读16位， 0x1000<<4
	je ok2_read 
	xor %ax, %ax
	sub %bx, %ax 
	shr $9, %ax 
ok2_read:
	call read_track
	mov %ax, %cx 
	add sread, %ax 
	cmp %cs:sectors, %ax 
	jne ok3_read 
	mov $1, %ax 
	sub head, %ax 
	jne ok4_read 
	incw track 
ok4_read:
	mov %ax, head 
	xor %ax, %ax 
ok3_read:
	mov %ax, sread 
	shl $9, %cx 
	add %cx, %bx 
	jnc rp_read
	mov %es, %ax 
	add $0x1000, %ax 
	mov %ax, %es 
	xor %bx, %bx 
	jmp rp_read

read_track:
	push %ax 
	push %bx 
	push %cx 
	push %dx 
	mov track, %dx 
	mov sread, %cx 
	inc %cx 		# cl: 开始读扇区
	mov %dl, %ch 	# ch: 当前磁道号
	mov head, %dx 	
	mov %dl, %dh 	# dh: 磁头号
	mov $0, %dl 	# dl: 0表示A驱动器
	and $0x0100, %dx  # 磁头不大于1
	mov $2, %ah 	# ah=2: 读磁盘功能号; al: 扇区数
	int $0x13		# 读到 es:bx 
	jc bad_rt
	pop %dx 
	pop %cx 
	pop %bx 
	pop %ax 
	ret 
bad_rt:
	mov $0, %ax
	mov $0, %dx 
	int $0x13
	pop %dx 
	pop %cx 
	pop %bx
	pop %ax 
	jmp read_track

kill_motor:
	push %dx 
	mov $0x3f2, %dx 
	mov $0, %al 
	outsb 
	pop %dx 
	ret 

	.org 506
swap_dev:
	.word SwapDev
root_dev:
	.word RootDev

	.word 0xaa55